package com.qfx.api.server.impl;

import java.util.Collection;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.stereotype.Service;

import com.qfx.api.entity.SysUser;
import com.qfx.api.server.LoginSer;
import com.qfx.common.service.BaseService;
import com.qfx.common.util.ToolResultCode;
import com.qfx.common.vo.MessageBean;

@Service
public class LoginSerImpl extends BaseService implements LoginSer {
	
	private final Logger logger = LogManager.getLogger(getClass());

	/**
	 * @功能描述：shiro登录验证,通过返回true,失败返回false
	 * 
	 * @param sysUser
	 * @return
	 */
	@Override
	public MessageBean login(SysUser sysUser) {
		MessageBean messageBean = new MessageBean();
		String code = "";
		String message = "";
		
		System.out.println("用户登录:userName["+sysUser.getUserName()+"],userPass["+sysUser.getPassword()+"]");
		
		// 1.使用shiro进行登录验证
		Subject subject = SecurityUtils.getSubject();
		UsernamePasswordToken token = new UsernamePasswordToken(sysUser.getUserName(), sysUser.getPassword());
		try {
			subject.login(token);
		} catch (UnknownAccountException e) {
			code = ToolResultCode.INFO_05;
			message = "用户不存在!";
		} catch (IncorrectCredentialsException e) {
			code = ToolResultCode.INFO_06;
			message = "用户密码出错!";
		} catch (ExcessiveAttemptsException e) {
			code = ToolResultCode.INFO_07;
			message = "登录失败多次，账户锁定10分钟";
		} catch (DisabledAccountException e) {
			code = ToolResultCode.INFO_08;
			message = "帐号已被禁用";
		} catch (AuthenticationException e) {
			code = ToolResultCode.INFO_9999;
			message = e.getMessage();
		}
		
		// 3.验证是否登录成功 (这里可以进行一些认证通过后的一些系统参数初始化操作)
		if(subject.isAuthenticated()){
			// 4.验证是否开启单用户登录
			boolean isSingleUseLogin = false;
			if (isSingleUseLogin) {
				// 单用户登录,清除当前用户以前登录时保存的session会话
				singleUseLogin(sysUser.getUserName());
			}
			logger.info("用户[" + sysUser.getUserName() + "]登录认证通过");
			System.out.println("用户[" + sysUser.getUserName() + "]登录认证通过");
			code = ToolResultCode.LOGIN_SUCCESS;
			message = "用户登录成功";
		}else{
			logger.info("用户[" + sysUser.getUserName() + "]进行登录验证失败,失败原因["+message+"]");
			System.out.println("用户[" + sysUser.getUserName() + "]进行登录验证失败,失败原因["+message+"]");
			token.clear();
		}
		messageBean.setCode(code);
		messageBean.setMessage(message);
			
		return messageBean;
	}
	
	// ==================== private method ====================
	
	/**
	 * @功能描述：	单用户登录,清除当前用户以前登录时保存的session会话
	 *
	 * @param request
	 * @param loginName
	 */
	private void singleUseLogin(String loginName){
		// 1.获取当前用户sessionId
		String currentUserSessionId = request.getSession().getId();
		
		// 2.获取shiro的sessionManager
		DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
    	DefaultWebSessionManager sessionManager = (DefaultWebSessionManager)securityManager.getSessionManager();
    	
    	// 3.获取所有已登录用户的session列表
    	Collection<Session> sessions = sessionManager.getSessionDAO().getActiveSessions();
        
    	String onlineSessionKey = "";
    	for(Session onlineSession:sessions){
    		// 4.获取已登录用户的session的key值
    		onlineSessionKey = String.valueOf(onlineSession.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY));
            // 5.清除当前用户以前登录时保存的session会话
        	System.out.println(onlineSession.getId()+"------" + onlineSessionKey);
            
            if (onlineSessionKey.equals("null")) {
            	sessionManager.getSessionDAO().delete(onlineSession);
			} else if (loginName.equals(onlineSessionKey) && !onlineSession.getId().equals(currentUserSessionId)) {
                sessionManager.getSessionDAO().delete(onlineSession);
            }
        }
	}
	

}
